<template>
    <view class="swipe-cell">
        <view
            :style="{
                'transition-duration': `${props.duration}s`,
                'transform': `translate3d(${movedDistance}rpx, 0rpx, 0rpx)`
            }"
            @touchstart="onTouchStart"
            @touchmove="onTouchMove"
            @touchend="onTouchEnd">
            <view
                v-if="props.leftWidth"
                class="swipe-cell__left"
                @tap="slotClick('left')">
                <slot name="left" />
            </view>
            <slot></slot>
            <view
                v-if="props.rightWidth"
                class="swipe-cell__right"
                @tap="slotClick('right')">
                <slot name="right" />
            </view>
        </view>
    </view>
</template>

<script lang="ts" setup>

    import {
    	ref,
		onMounted
    } from "vue";

    const emits = defineEmits(["close", "swipeEnd"]);
    const props = defineProps({
    	duration: {
    	    type: Number,
    	    default: 0.4
    	},
    	// 右边slot 的宽度 rpx为单位
    	rightWidth: {
    	    type: Number,
    	    default: 0
    	},
    	// 左边slot 的宽度 rpx为单位
    	leftWidth: {
    	    type: Number,
    	    default: 0
    	},
    	// prop传进来的滑动距离
    	propMovedDistance: {
    	    type: Number,
    	    default: 0
    	}
    });

    const movedDistance = ref(0); // 元素应该滑动的距离
    const swipeable = ref(true);
    const swiping = ref(false);
    const direction = ref("");
    const deltaX = ref(0);
    const deltaY = ref(0);
    const offsetX = ref(0);
    const offsetY = ref(0);
    const startX = ref(0);
    const startY = ref(0);
    const minSwipeDistance = ref(50);

    function touchStart (event: any) {
        resetTouchStatus();
        var touch = event.touches[0];
        startX.value = touch.clientX;
        startY.value = touch.clientY;
    }
    function touchMove (event: any) {
        var touch = event.touches[0];
        deltaX.value = touch.clientX - startX.value;
        deltaY.value = touch.clientY - startY.value;
        offsetX.value = Math.abs(deltaX.value);
        offsetY.value = Math.abs(deltaY.value);
        direction.value = direction.value || getDirection(offsetX.value, offsetY.value);
    }
    function onTouchStart (event: any) {
        if (!swipeable.value) { return; }
        swiping.value = true;
        touchStart(event);
    }
    function onTouchMove (event: any) {
        if (!swipeable.value || !swiping.value) { return; }
        touchMove(event);
    }
    // watch swipe touch end
    function onTouchEnd () {
        if (!swipeable.value || !swiping.value) { return; }
        if (!props.leftWidth && deltaX.value > 0 && !movedDistance.value) return;
        if (!props.rightWidth && deltaX.value < 0 && !movedDistance.value) return;
        if (direction.value === 'horizontal' && offsetX.value >= minSwipeDistance.value) {
            movedDistance.value = deltaX.value > 0 ? props.leftWidth : -props.rightWidth;
        }
        swiping.value = false;
        emits('swipeEnd', movedDistance.value);
    }
    function slotClick (type) {
        movedDistance.value = 0;
        resetTouchStatus();
        emits('close', type);
    }
    function getMovedDistance () {
        return movedDistance.value;
    }

    /**
     * 获取滑动的方向，垂直、水平
     * @param {*} x
     * @param {*} y
     * @returns horizontal: 水平； vertical: 垂直
     */
    function getDirection(x: any, y: any) {
        var MIN_DISTANCE = 10;
        if (x > y && x > MIN_DISTANCE) {
            return 'horizontal';
        }
        if (y > x && y > MIN_DISTANCE) {
            return 'vertical';
        }
        return '';
    }

    function resetTouchStatus () {
        direction.value = '';
        deltaX.value = 0;
        deltaY.value = 0;
        offsetX.value = 0;
        offsetY.value = 0;
    }

    onMounted(() => {
        movedDistance.value = props.propMovedDistance;
    })
	
</script>

<style lang="scss" scoped>
	.swipe-cell {
	    overflow: hidden;
	    position: relative;
	    &__left {
	        position: absolute;
	        top: 0;
	        height: 100%;
	        left: 0;
	        transform: translate3d(-100%, 0, 0);
	    }
	    &__right {
	        position: absolute;
	        top: 0;
	        height: 100%;
	        right: 0;
	        transform: translate3d(100%, 0, 0);
	    }
	}
</style>